#include"ThreadCache.h"
#include"CentralCache.h"


//类外定义
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
	//慢开始反馈算法
	//最开始不会向Centralcache索要太多，避免用不完
	//但后面不断有相同需求，则加大移动该大小的内存块数量，知道上限
	//size越大，则单次向centralcache所要的块数越小
	//size越小，则单次向centralcache所要的块数越大
	size_t batchNum = min(_freeLists[index].MaxSize(), SizeClass::NumMoveSize(size));
	if (batchNum == _freeLists[index].MaxSize())
	{
		_freeLists[index].MaxSize() += 1;     //MaxSize()返回引用，可进行修改
	}

	void* start = nullptr;
	void* end = nullptr;
	size_t actualNum = CentralCache::GetInstance()->FetchRangeObj(start, end, batchNum, size);
	assert(actualNum >= 1);
	if (actualNum == 1)
	{
		assert(start == end);
		return start;
	}
	else
	{
		_freeLists[index].PushRange(NextObj(start), end,actualNum-1);
		return start;
	}
	//return nullptr;
}


void* ThreadCache::Allocate(size_t size)     //生成
{
	assert(size <= MAX_BYTES);
	size_t alignSize = SizeClass::RoundUp(size);    //内存块大小
	size_t index = SizeClass::Index(alignSize);          //哈希桶下标

	if (!_freeLists[index].Empty())        //桶剩余，则先从桶里获取
	{
		return _freeLists[index].Pop();         
	}
	else          //桶空了后，向中心缓存获取
	{
		return FetchFromCentralCache(index, alignSize);
	}
}

void ThreadCache::Deallocate(void* ptr, size_t size)   //释放
{
	assert(ptr);
	//assert(size < MAX_BYTES);

	//找到映射的自由链表桶，对象插入进去
	size_t index = SizeClass::Index(size);
	_freeLists[index].Push(ptr);

	//当链表的长度大于一次批量申请的内存时，就开始还一段链表给centralcache
	if (_freeLists[index].Size() >= _freeLists[index].MaxSize())
	{
		ListToolong(_freeLists[index], size);
	}
}

void ThreadCache::ListToolong(FreeList& list, size_t size)
{
	void* start = nullptr;
	void* end = nullptr;
	list.PopRange(start, end, list.MaxSize());

	CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}